<template>
  <div>
    <!--管理-->
    <el-button-group v-if="isManage">
      <el-button v-if="useLocale&&hasInitPermi" type="warning" plain size="small" icon="el-icon-bangzhu"
                 @click="syncFromStandard">
        从行政区划代码库初始化
      </el-button>
      <el-button v-if="hasInitPermi" type="warning" plain size="small" icon="el-icon-upload"
                 @click="upload.open=true">导入
      </el-button>
      <el-button v-if="useLocale&&hasInitPermi" type="danger" plain size="small" icon="el-icon-s-open" @click="cleanCache">清空缓存</el-button>
      <el-button size="small" icon="el-icon-plus" plain @click="showAddPanel" type="primary">新增地区</el-button>
    </el-button-group>
    <!--ztree-->
    <ul :id="id" class="ztree"></ul>

    <!-- 导入 -->
    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
      <el-upload
        ref="upload"
        :limit="1"
        accept=".csv"
        :headers="upload.headers"
        :action="upload.url + '?cleanImport=' + upload.cleanImport+'&useLocale='+useLocale"
        :disabled="upload.isUploading"
        :on-progress="handleFileUploadProgress"
        :on-success="handleFileSuccess"
        :auto-upload="false"
        drag
      >
        <i class="el-icon-upload"></i>
        <div class="el-upload__text">
          将文件拖到此处，或
          <em>点击上传</em>
        </div>
        <div class="el-upload__tip" slot="tip">
          <el-checkbox v-model="upload.cleanImport"/>
          上传时是否清除原地区数据
          <el-link type="info" style="font-size:12px" :href="baseAPI+'/system/area/importTemplate'">下载模板</el-link>
        </div>
        <div class="el-upload__tip" style="color:red" slot="tip">提示：仅允许导入csv格式文件！</div>
      </el-upload>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="submitFileForm">确 定</el-button>
        <el-button @click="upload.open = false">取 消</el-button>
      </div>
    </el-dialog>

    <!--编辑地区-->
    <el-dialog :title="editForm.title" :visible.sync="editForm.open" width="400px" append-to-body>
      <el-form ref="editForm" :model="editForm" label-width="80px" :rules="editFormRules">
        <el-form-item label="地区名称" prop="name">
          <el-input v-model="editForm.name"></el-input>
        </el-form-item>
        <el-form-item label="地区码" prop="subCode">
          <el-input v-model="editForm.subCode">
            <template slot="prepend" v-if="editForm.parentCode!==''">{{ editForm.parentCode }}</template>
          </el-input>
          <br>
          应填写地区码位数: {{ editForm.oldCode.length - editForm.parentCode.length }}
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="primary" @click="confirmEdit">确 定</el-button>
        <el-button @click="editForm.open = false">取 消</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import {getToken} from "@/utils/auth";
import {
  listByParent,
  getByCode,
  syncFromStandard,
  removeAreas,
  saveArea,
  dropArea,
  cleanCaches
} from "@/api/system/area";

let baseApi = process.env.VUE_APP_BASE_API;
export default {
  name: "AreaTreeRender",
  data() {
    let _this = this;
    return {
      treeObj: null,
      treeNodes: [],
      baseAPI: baseApi,
      id: 'tree-' + Math.round(Math.random() * 100000),
      //是否有初始化权限
      hasInitPermi: this.$auth.hasPermi('system:area:init'),
      upload: {
        // 是否显示弹出层
        open: false,
        // 弹出层标题
        title: "导入地区表",
        // 是否禁用上传
        isUploading: false,
        // 是否清除数据后再上传
        cleanImport: true,
        // 设置上传的请求头部
        headers: {Authorization: "Bearer " + getToken()},
        // 上传的地址
        url: baseApi + "/system/area/importAreas"
      },
      //根节点
      rootNode: null,
      //添加或编辑表单
      editForm: {
        open: false,
        title: '',
        id: undefined,
        oldCode: '',
        name: '',
        parentCode: '',
        subCode: ''
      },
      editFormRules: {
        name: [{required: true, message: '地区名称不能为空', trigger: 'blur'}],
        subCode: [{
          validator(rule, value, callback) {
            //判断长度
            let oldCode = _this.editForm.oldCode;
            let parentCode = _this.editForm.parentCode;
            let subCode = _this.editForm.subCode;
            let id = _this.editForm.id;
            let nums = oldCode.length - parentCode.length;
            if (!/^\d+$/.test(value)) {
              callback(new Error('地区码必须为数字'));
            } else if (value.length !== nums) {
              callback(new Error('地区码位数不符合规范'));
            } else {
              //判断是否有多个
              let parentNode = _this.treeObj.getNodeByParam('code', parentCode);
              if (!parentNode.isParent) {
                callback();
                return;
              }
              let curCode = parentCode + subCode;
              let curCodeNodes = parentNode.children.filter((node) => {
                return node.code === curCode && node.id !== id;
              });
              if (curCodeNodes.length > 0) {
                callback(new Error('已存在相同地区码'));
              } else {
                callback();
              }
            }
          }, trigger: 'blur'
        }]
      }
    };
  },
  props: {
    //是否使用本地区划码
    useLocale: {
      type: Boolean,
      default: true
    },
    //树的跟地区,默认为0
    rootCode: {
      type: String,
      default: ''
    },
    //最大级别,默认村级
    maxLevel: {
      type: Number,
      default: 5
    },
    //是否管理,默认不参与
    isManage: {
      type: Boolean,
      default: false
    }
  },
  //组件销毁时注销地区树
  destroyed() {
    $.fn.zTree.destroy(this.id);
  },
  //初始化树结构
  mounted() {
    let _this = this;
    let maxLevel = this.maxLevel;
    let isManage = this.isManage;
    //获取跟节点信息
    this.getRootInfo().then(info => {
      this.treeNodes.push(info);
      let setting = {
        async: {
          enable: true,
          url: `${_this.baseAPI}/system/area/listByParent`,
          autoParam: ["code=parentCode"],
          otherParam: {
            useLocale: this.useLocale
          },
          headers: {Authorization: "Bearer " + getToken()},
          dataFilter(treeId, parentNode, responseData) {
            return responseData.data.map(d => {
              return {
                id: d.id,
                name: d.name,
                nameWithCode: `${d.name}` + (d.code ? `[${d.code}]` : ''),
                title: `${d.name}` + (d.code ? `[${d.code}]` : ''),
                code: d.code,
                parentCode: d.parentCode,
                adLevel: d.level,
                isParent: d.parent && d.level < maxLevel,
                childCount: d.childCount
              };
            });
          }
        },
        data: {
          simpleData: {
            enable: true,
            idKey: 'code',
            pIdKey: 'parentCode',
            rootPId: this.finalRootCode,

          },
          key: {
            name: 'nameWithCode'
          }
        },
        view: {
          //添加自定义组件
          addHoverDom(treeId, treeNode) {
          }
        },
        edit: {
          enable: true,
          editNameSelectAll: false,
          showRemoveBtn(treeId, treeNode) {
            return isManage && treeNode.level > 0
          },
          removeTitle: '删除地区',
          showRenameBtn(treeId, treeNode) {
            return isManage && treeNode.level > 0
          },
          renameTitle: '修改地区',
          drag: {
            isCopy: false,
            isMove: _this.isManage,
            prev: false,
            next: false,
            inner: true
          }
        },
        callback: {
          //删除
          beforeRemove(treeId, treeNode) {

            _this.$confirm('确认要删除该地区及其所有下级地区?', {
              type: 'warning'
            }).then(() => {
              //实现自己的删除逻辑
              let loadingIns = _this.$modal.loading('正在删除,请稍后...');
              removeAreas(_this.useLocale, treeNode.code).then((res) => {
                loadingIns.close();
                if (res.code === 200) {
                  _this.$modal.msgSuccess(res.msg);
                } else {
                  _this.$modal.msgError(res.msg);
                }
                //重新加载节点
                _this.treeObj.removeNode(treeNode);
              }).catch(() => {
                loadingIns.close();
                _this.$modal.msgError('操作失败, 网络异常');
              })
            }).catch(() => {
            });
            return false
          },
          //修改
          beforeEditName(treeId, treeNode) {
            _this.editForm.open = true;
            _this.editForm.title = '修改地区';
            _this.editForm.name = treeNode.name;
            _this.editForm.parentCode = treeNode.parentCode;
            _this.editForm.id = treeNode.id;
            _this.editForm.oldCode = treeNode.code;
            _this.editForm.subCode = treeNode.code.substr(treeNode.parentCode.length);
            return false;
          },
          //判断是否允许拖拽 当前模式设置为只能拖拽到下级,且拖拽的目标节点为最终的父节点
          beforeDrop(treeId, treeNodes, targetNode) {
            //判断树节点
            if (_this.id !== treeId) {
              _this.$modal.msgError('只能再同一棵树之间移动');
              return false;
            }
            //判断地区层级
            if (targetNode.adLevel !== treeNodes[0].adLevel - 1) {
              _this.$modal.msgError('地区移动前后必须为同一层级');
              return false;
            }
            //判断地区码移动后是否变为为重复
            let repeatNames = [];
            let children = targetNode.children;
            let parentCode = targetNode.code;
            children.forEach((targetChildNode) => {
              let targetSubCode = targetChildNode.code.substr(parentCode.length);
              treeNodes.forEach((node) => {
                let subCode = node.code.substr(parentCode.length);
                if (targetSubCode === subCode) {
                  repeatNames.push(node.name)
                }
              })
            });
            if (repeatNames.length > 0) {
              _this.$modal.msgError('地区移动后将会有重复地区码,请先修改地区码然后再移动;将重复的地区为: ' + repeatNames.join(','));
              return false;
            }
            return true;
          },
          //拖拽后
          onDrop(event, treeId, treeNodes, targetNode) {
            //组装节点 useLocale,id,name,code,parentCode
            let parentCode = targetNode.code;
            let areas = treeNodes.map(node => {
              return {
                useLocale: _this.useLocale,
                id: node.id,
                name: node.name,
                parentCode: parentCode,
                code: parentCode + node.code.substr(parentCode.length)
              };
            });
            let loadingIns = _this.$modal.loading('正在移动地区,请稍后...');
            dropArea(areas).then(res => {
              loadingIns.close();
              if (res.code === 200) {
                _this.$modal.msgSuccess(res.msg);
                //重新加载目标节点刷新地区码
                _this.treeObj.reAsyncChildNodes(targetNode, 'refresh');
              } else {
                _this.$modal.msgError(res.msg);
              }
            }).catch(() => {
              loadingIns.close();
              _this.$modal.msgError('操作失败,网络异常');
            })
          },
          //点击事件,交由父组件监听
          onClick(event, treeId, treeNode) {
            _this.$emit('select', treeNode);
          }
        }
      };
      this.treeObj = $.fn.zTree.init($(`#${this.id}`), setting, this.treeNodes);
      //展开第一级
      this.expandRoot();
    })

  },
  methods: {

    /**
     * 获取根节点信息
     */
    async getRootInfo() {
      let rootCode = this.finalRootCode;
      //获取节点信息
      let info = await getByCode(this.useLocale, rootCode);
      let d = info.data;
      return {
        name: d.name,
        nameWithCode: `${d.name}` + (d.code ? `[${d.code}]` : ''),
        title: `${d.name}` + (d.code ? `[${d.code}]` : ''),
        code: d.code,
        parentCode: d.parentCode,
        adLevel: d.level,
        isParent: d.level < this.maxLevel
      };
    },

    /**
     * 展开根节点
     */
    expandRoot() {
      let treeObj = this.treeObj;
      let rootNode = treeObj.getNodeByParam('code', this.finalRootCode);
      if (rootNode) {
        this.rootNode = rootNode;
        treeObj.expandNode(rootNode);
      }
    },
    // 文件上传中处理
    handleFileUploadProgress(event, file, fileList) {
      this.upload.isUploading = true;
      this.loadingIns = this.$modal.loading('正在导入地区数据,请稍后...');
    },
    // 文件上传成功处理
    handleFileSuccess(response, file, fileList) {
      if (this.loadingIns) {
        this.loadingIns.close();
        this.loadingIns = null;
      }
      this.upload.open = false;
      this.upload.isUploading = false;
      this.$refs.upload.clearFiles();
      this.$alert(response.msg, "导入结果", {dangerouslyUseHTMLString: true});
      //重新加载地区树
      this.treeObj.reAsyncChildNodes(this.rootNode, 'refresh');
    },
    // 提交上传文件
    submitFileForm() {
      this.$refs.upload.submit();
    },
    //初始化
    syncFromStandard() {
      this.$confirm('确认要初始化本地地址码库? 初始化后本地地址码库将由标准地址码同步.').then(() => {
        let loadingIns = this.$modal.loading('正在初始化,请稍后...');
        syncFromStandard().then(res => {
          loadingIns.close();
          this.$alert(res.msg);
          this.treeObj.reAsyncChildNodes(this.rootNode, 'refresh');
        }).catch(() => {
          loadingIns.close();
          this.$alert('操作失败,网络异常');
        });
      }).catch(() => {
      });
    },
    //打开
    showAddPanel() {
      //当前选中
      let selNodes = this.treeObj.getSelectedNodes();
      if (selNodes.length !== 1) {
        this.$modal.msgError('添加时请选中唯一节点');
        return;
      }
      let treeNode = selNodes[0];
      if (this.maxLevel <= treeNode.adLevel) {
        this.$modal.msgError('选中节点为最底层节点,无法继续添加地区');
        return;
      }
      let oldCodesForLevel = ['', '00', '0000', '000000', '000000000', '000000000000'];
      this.editForm.open = true;
      this.editForm.title = '添加地区';
      this.editForm.name = '';
      this.editForm.parentCode = treeNode.code;
      this.editForm.id = undefined;
      this.editForm.oldCode = oldCodesForLevel[treeNode.adLevel + 1];
      this.editForm.subCode = '';
    },
    //确认编辑地区
    confirmEdit() {
      let parentCode = this.editForm.parentCode;
      this.$refs['editForm'].validate((valid) => {
        if (valid) {
          let loadingIns = this.$modal.loading('正在保存,请稍后...');
          saveArea({
            id: this.editForm.id,
            name: this.editForm.name,
            code: parentCode + this.editForm.subCode,
            parentCode: parentCode,
            useLocale: this.useLocale
          }).then(res => {
            loadingIns.close();
            res.code === 200 ? this.$modal.msgSuccess(res.msg) : this.$modal.msgError(res.msg);
            this.editForm.open = false;
            //重新加载
            let parentNode = this.treeObj.getNodeByParam('code', parentCode);
            this.treeObj.reAsyncChildNodes(parentNode, 'refresh');
          }).catch(() => {
            loadingIns.close();
            this.$modal.msgError('保存失败,网络异常')
          })
        }
      })

    },

    //清空缓存
    cleanCache() {
      this.$modal.confirm('确认要清空缓存?').then(() => {
        cleanCaches().then(res => {
          this.$modal.msgAlert(res);
        })
      })
    }
  },
  computed: {
    finalRootCode() {
      return this.rootCode || this.$store.getters.areaInfo.code;
    }
  }
}
</script>

<style scoped>

.btn-color {
  background-color: #2AA6A6 !important;
}
</style>
